﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Composition;
using System.Runtime.CompilerServices;
using Windows.Storage;
using CC98.Network;
using CC98.Network.Primitives;

namespace CC98.UserSession
{
    /// <summary>
    /// Manage all user sessions and handle network session save & restore
    /// </summary>
    [Shared]
    [Export(typeof(UserSessionManager))]
    public class UserSessionManager : SingleInstanceObject, INotifyPropertyChanged
    {
        [ImportingConstructor]
        public UserSessionManager(ICC98HttpClientPool httpClientPool)
        {
            this._httpClientPool = httpClientPool;
        }

        /// <summary>
        /// Current session
        /// </summary>
        public UserSessionInstance Current
        {
            get
            {
                return _current;
            }
            set
            {
                if (this._current != value)
                {
                    this._current = value;
                    this.OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// Get one session
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public UserSessionInstance GetSession(string username)
        {
            if (string.IsNullOrWhiteSpace(username))
                throw new ArgumentException("Invalid username");

            lock (this)
            {
                UserSessionInstance session = null;
                if (!this._sessionDict.TryGetValue(username, out session))
                {
                    session = new UserSessionInstance(new CC98Client(this._httpClientPool.GetClient(username)));
                    session.AuthenticationStateChanged += Session_AuthenticationStateChanged;
                    this._sessionDict[username] = session;
                }
                return session;
            }
        }

        /// <summary>
        /// Get all sessions
        /// </summary>
        /// <returns></returns>
        public IEnumerable<UserSessionInstance> GetSessions()
        {
            lock (this)
            {
                var instances = new UserSessionInstance[this._sessionDict.Count];

                this._sessionDict.Values.CopyTo(instances, 0);

                return instances;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnSessionCollectionChanged()
        {
            if (this.SessionCollectionChanged != null)
                this.SessionCollectionChanged(this, new EventArgs());
        }

        protected void OnSessionAuthenticationChanged(UserSessionInstance session, AuthenticationStateChangedEventArgs e)
        {
            if (this.SessionAuthenticationStateChanged != null)
                this.SessionAuthenticationStateChanged(this, new SessionAuthenticationStateChangedEventArgs(session));
        }

        protected virtual void OnPropertyChanged([CallerMemberName]string name = null)
        {
            var callback = this.PropertyChanged;
            if (callback != null)
                callback(this, new PropertyChangedEventArgs(name));
        }

        public event EventHandler SessionCollectionChanged;

        public event EventHandler<SessionAuthenticationStateChangedEventArgs> SessionAuthenticationStateChanged;

        public event EventHandler CurrentChanged;

        private readonly Dictionary<string, UserSessionInstance> _sessionDict = new Dictionary<string, UserSessionInstance>();

        private ICC98HttpClientPool _httpClientPool;

        private UserSessionInstance _current;

        private void Session_AuthenticationStateChanged(object sender, AuthenticationStateChangedEventArgs e)
        {
            this.OnSessionAuthenticationChanged((UserSessionInstance)sender, e);
        }

        
    }
}
